#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dml/dml.h>
#include <string.h>
#include <extensions/gldml.h>
#include "engine.h"

int tempvertex_model1;
int tempvertex_model2;
float tempx,tempy,tempz;

void drawobject(s_mesh *mesh)

{
int a,b,c,ta,tb,tc,na,nb,nc;
int i;

//glColor3f(1,1,1);
glBegin(GL_TRIANGLES);				

for (i=0;i<mesh->numfaces;i++) {
    // get a,b,c, indices
    a=mesh->face[i].a;b=mesh->face[i].b;c=mesh->face[i].c;
    ta=mesh->face[i].ta;tb=mesh->face[i].tb;tc=mesh->face[i].tc;
    na=mesh->face[i].na;nb=mesh->face[i].nb;nc=mesh->face[i].nc;
    
    // defineer de 3 vertices van de triangle
    glNormal3f(mesh->normals[na].x, mesh->normals[na].y,mesh->normals[na].z);
    glTexCoord2f(mesh->tvertex[ta].u, mesh->tvertex[ta].v);
    glVertex3f(mesh->vertex[a].x,mesh->vertex[a].y,mesh->vertex[a].z);
    
    glNormal3f(mesh->normals[nb].x, mesh->normals[nb].y,mesh->normals[nb].z);
    glTexCoord2f(mesh->tvertex[tb].u, mesh->tvertex[tb].v);
    glVertex3f(mesh->vertex[b].x,mesh->vertex[b].y,mesh->vertex[b].z);
    
    glNormal3f(mesh->normals[nc].x, mesh->normals[nc].y,mesh->normals[nc].z);
    glTexCoord2f(mesh->tvertex[tc].u, mesh->tvertex[tc].v);
    glVertex3f(mesh->vertex[c].x,mesh->vertex[c].y,mesh->vertex[c].z);
    
}
glEnd();
}


void LoadMesh(char *fn,s_mesh *mesh)

{
FILE *f;
char str[256],id[16];
float x,y,z;
int a,b,c,ta,tb,tc,na,nb,nc;


mesh->numvertices=0;
mesh->numtvertices=0;
mesh->numfaces=0;
mesh->numnormals=0;

// Count verts/faces for allocation
f=fopen(fn,"rt");
do {
fgets(str,256,f);       // lees regel in
sscanf(str,"%s",id);    // lees id uit string
if (!strcmp(id,"v")) mesh->numvertices++;
if (!strcmp(id,"vt")) mesh->numtvertices++;
if (!strcmp(id,"f")) mesh->numfaces++;
if (!strcmp(id,"vn")) mesh->numnormals++;
}while(!feof(f));
fclose(f);

mesh->vertex=(s_vertex*)malloc(mesh->numvertices*sizeof(s_vertex));
mesh->tvertex=(s_tvertex*)malloc(mesh->numtvertices*sizeof(s_tvertex));
mesh->face=(s_face*)malloc(mesh->numfaces*sizeof(s_face));
mesh->normals=(s_normals*)malloc(mesh->numnormals*sizeof(s_normals));

// Read object
mesh->numvertices=0;
mesh->numtvertices=0;
mesh->numfaces=0;
mesh->numnormals=0;

f=fopen(fn,"rt");
do {

fgets(str,256,f);       // lees regel in

sscanf(str,"%s",id);    // lees id uit string
printf("ID is: %s\n",id);

// LEES VERTEX
if (!strcmp(id,"v")) {  // als id gelijk is aan 'v'
   sscanf(str,"v %f %f %f",&x,&y,&z);   // lees rest van de regel x,y,z
   printf("VERTEX: %f %f %f\n",x,y,z);
   mesh->vertex[mesh->numvertices].x=x/10;
   mesh->vertex[mesh->numvertices].y=y/10;
   mesh->vertex[mesh->numvertices].z=z/10;
   mesh->numvertices++;
}

// LEES TEXTURED VERTEX (u,v)
if (!strcmp(id,"vt")) {  // als id gelijk is aan 'v'
   sscanf(str,"vt %f %f %f",&x,&y,&z);   // lees rest van de regel x,y,z
   printf("TVERTEX: %f %f %f\n",x,y,z);
   mesh->tvertex[mesh->numtvertices].u=x;
   mesh->tvertex[mesh->numtvertices].v=1-y;
   mesh->numtvertices++;
}

// LEES NORMALS (x,y,z)

if (!strcmp(id,"vn")) {  // als id gelijk is aan 'v'
   sscanf(str,"vn %f %f %f",&x,&y,&z);   // lees rest van de regel x,y,z
   printf("NORMAL: %f %f %f\n",x,y,z);
   mesh->normals[mesh->numnormals].x=x;
   mesh->normals[mesh->numnormals].y=y;
   mesh->normals[mesh->numnormals].z=z;
   mesh->numnormals++;
}

// LEES FACES
if (!strcmp(id,"f")) {  // als id gelijk is aan 'v'
   sscanf(str,"f %d/%d/%d %d/%d/%d %d/%d/%d",&a,&ta,&na,&b,&tb,&nb,&c,&tc,&nc);   // lees rest van de regel x,y,z
   printf("FACE: %d %d %d\n",a,b,c);
   mesh->face[mesh->numfaces].a=a-1;
   mesh->face[mesh->numfaces].b=b-1;
   mesh->face[mesh->numfaces].c=c-1;
   mesh->face[mesh->numfaces].ta=ta-1;
   mesh->face[mesh->numfaces].tb=tb-1;
   mesh->face[mesh->numfaces].tc=tc-1;
   mesh->face[mesh->numfaces].na=na-1;
   mesh->face[mesh->numfaces].nb=nb-1;
   mesh->face[mesh->numfaces].nc=nc-1;
   mesh->numfaces++;
}

}while(!feof(f));  // zolang niet einde file
fclose(f);
}

void DeleteMesh(s_mesh *mesh)

{
mesh->numvertices=0;
mesh->numtvertices=0;
mesh->numfaces=0;
free(mesh->vertex);
free(mesh->tvertex);
free(mesh->face);
}

void color(int r, int g, int b)
{
    float multiplier;

    multiplier = 1.0f / 255;


    float red,green,blue;
    red     = (float) r * multiplier;
    green   = (float) g * multiplier;
    blue    = (float) b * multiplier;

    glColor3f(red,green,blue);
}

void Draw_Quads(float x, float y, float z, float size)
{
    glTranslatef(x,y,z);

    float size_large,size_small;

    size_large = 0.0f;
    size_small = 0.0f;

    size_large = size;
    size_small = size_small - size;

    glBegin(GL_QUADS);
        color(0, 255, 0);			       // Set The Color To Green
		glVertex3f(size_large,size_large,size_small);			// Top Right Of The Quad (Top)
		glVertex3f(size_small,size_large,size_small);			// Top Left Of The Quad (Top)
		glVertex3f(size_small,size_large,size_large);			// Bottom Left Of The Quad (Top)
		glVertex3f(size_large,size_large,size_large);			// Bottom Right Of The Quad (Top)

					     // Set The Color To Orange
		glVertex3f(size_large,size_small,size_large);			// Top Right Of The Quad (Bottom)
		glVertex3f(size_small,size_small,size_large);			// Top Left Of The Quad (Bottom)
		glVertex3f(size_small,size_small,size_small);			// Bottom Left Of The Quad (Bottom)
		glVertex3f(size_large,size_small,size_small);			// Bottom Right Of The Quad (Bottom)

		//glColor3f(1.0f,0.0f,0.0f);			     // Set The Color To Red
		glVertex3f(size_large,size_large,size_large);			// Top Right Of The Quad (Front)
		glVertex3f(size_small,size_large,size_large);			// Top Left Of The Quad (Front)
		glVertex3f(size_small,size_small,size_large);			// Bottom Left Of The Quad (Front)
		glVertex3f(size_large,size_small,size_large);			// Bottom Right Of The Quad (Front)

		//glColor3f(1.0f,1.0f,0.0f);			     // Set The Color To Yellow
		glVertex3f(size_large,size_small,size_small);			// Bottom Left Of The Quad (Back)
		glVertex3f(size_small,size_small,size_small);			// Bottom Right Of The Quad (Back)
		glVertex3f(size_small,size_large,size_small);			// Top Right Of The Quad (Back)
		glVertex3f(size_large,size_large,size_small);			// Top Left Of The Quad (Back)

		//glColor3f(0.0f,0.0f,1.0f);			     // Set The Color To Blue
		glVertex3f(size_small,size_large,size_large);			// Top Right Of The Quad (Left)
		glVertex3f(size_small,size_large,size_small);			// Top Left Of The Quad (Left)
		glVertex3f(size_small,size_small,size_small);			// Bottom Left Of The Quad (Left)
		glVertex3f(size_small,size_small,size_large);			// Bottom Right Of The Quad (Left)

		//glColor3f(1.0f,0.0f,1.0f);			     // Set The Color To Violet
		glVertex3f( size_large,size_large,size_small);			// Top Right Of The Quad (Right)
		glVertex3f( size_large,size_large,size_large);			// Top Left Of The Quad (Right)
		glVertex3f( size_large,size_small,size_large);			// Bottom Left Of The Quad (Right)
		glVertex3f( size_large,size_small,size_small);			// Bottom Right Of The Quad (Right)
	glEnd();						// Done Drawing The Quad
}


ALboolean LoadWav(char *fn,s_openal *sound, float pos_x,float pos_y,float pos_z, float velo_x, float velo_y, float velo_z)
{
	// Position of the source sound.
    ALfloat SourcePos[] = { pos_x, pos_y, pos_z };
    // Velocity of the source sound.
    ALfloat SourceVel[] = { velo_x, velo_y, velo_z };

        
    // Load wav data into a buffer.
	alGenBuffers(1, &sound->Buffer);

	if(alGetError() != AL_NO_ERROR)
		return AL_FALSE;

	alutLoadWAVFile(fn, &sound->format, &sound->data, &sound->size, &sound->freq, &sound->loop);
    alBufferData(sound->Buffer, sound->format, sound->data, sound->size, sound->freq);
    alutUnloadWAV(sound->format, sound->data, sound->size, sound->freq);

	// Bind the buffer with the source.
	alGenSources(1, &sound->Source);

	if(alGetError() != AL_NO_ERROR)
		return AL_FALSE;

	alSourcei (sound->Source, AL_BUFFER,   sound->Buffer  );
	alSourcef (sound->Source, AL_PITCH,    1.0      );
	alSourcef (sound->Source, AL_GAIN,     1.0      );
	alSourcefv(sound->Source, AL_POSITION, SourcePos);
	alSourcefv(sound->Source, AL_VELOCITY, SourceVel);
	alSourcei (sound->Source, AL_LOOPING,  sound->loop    );

	// Do another error check and return.
	if(alGetError() == AL_NO_ERROR)
		return AL_TRUE;

	return AL_FALSE;
}

void DeleteSound(s_openal *sound)
{
    alDeleteBuffers(1, &sound->Buffer);
	alDeleteSources(1, &sound->Source);
}

void MoveWav(s_openal *sound, float x, float y, float z)
{
    ALfloat SourcePos[] = { x, y, z };
    alSourcefv(sound->Source, AL_POSITION, SourcePos);
}

void PlaySound(s_openal *sound)
{
    alSourcePlay(sound->Source);
}

void StopSound(s_openal *sound)
{
    alSourceStop(sound->Source);
}

/*
 * ALboolean InitOpenAL()
 *
 *  Gets a handle to the sound device, and obtains a context to stream
 *  audio samples through.
 */
ALboolean InitOpenAL()
{

    ALCdevice* pDevice;
    ALCcontext* pContext;
    ALCubyte* defaultDevice;

    // Get handle to device.

    pDevice = alcOpenDevice((ALCubyte*)"DirectSound3D");

    // Get the device specifier.

    //defaultDevice = alcGetString(pDevice, ALC_DEVICE_SPECIFIER);

    //printf("Using device '%s'.\n", defaultDevice);

    // Create audio context.

    pContext = alcCreateContext(pDevice, NULL);

    // Set active context.

    alcMakeContextCurrent(pContext);

    // Do an error check.

    if(alcGetError(pDevice) != ALC_NO_ERROR)
        return AL_FALSE;
        
    alGetError(); // Clear the bit.

    return AL_TRUE;
}


bool CheckCollision(s_mesh *model1, s_mesh *model2, float x_model1, float y_model1, float z_model1, float x_model2, float y_model2, float z_model2)
{
    for (int i=0;i<model1->numtvertices;i++) 
    {
        for (int j=0;j<model2->numtvertices;j++)
        {
            //check of model2.x groter is dan model1.x
            if((model1->vertex[i].x+x_model1) > (model2->vertex[j].x+x_model2)) 
            {
                if((model1->vertex[i].x - model2->vertex[j].x) < tempx) 
                {
                    tempx = (model1->vertex[i].x-model2->vertex[j].x);
                    tempvertex_model1 = i;
                    tempvertex_model2 = j;

                }
            }
            
            //check of model2.x lager is dan model1.x
            if((model1->vertex[i].x+x_model1) < (model2->vertex[j].x+x_model2))
            {
                if((model2->vertex[j].x - model1->vertex[i].x) < tempx)
                {
                    tempx = (model2->vertex[j].x - model1->vertex[i].x);
                    tempvertex_model1 = i;
                    tempvertex_model2 = j;
                }
            }
         }
    }
    printf("Model1 x: %f, Model2 x: %f \n", (model1->vertex[tempvertex_model1].x+x_model1), (model2->vertex[tempvertex_model2].x+x_model2));
}
